#include <stdio.h>
#include <iostream>

#include "../util.h"
#include "CScn.h"

using namespace irr;
using namespace video;

void CScn::reset()
{
    solids=0;
    ents=0;
    header=0;
}

//default constructor
CScn::CScn ()
{
    reset();
}

//constructor that reads scn file
CScn::CScn(std::ifstream * file)
{
    reset();
    loadFile(file);
}

//destructor
CScn::~CScn()
{
    if (solids)
        delete [] solids;

    if (header)
        delete header;

    if (ents)
        delete [] ents;
}

int CScn::loadFile(std::ifstream * file)
{
    //IMPORTANT: load must be in this order so we don't have to store addresses
    loadHeader(file);
    solids = (CScnSolid*) new (std::nothrow) CScnSolid[header->n_solids];

    if (!solids)
        error(true,"Error allocating %u CScnSolid's", header->n_solids);

    solids[0].offset=header->solid0_offset;
    solids[0].length=header->solid0_length;

    for (u32 i=0; i < header->n_solids; i++)
    {

        SAY("Getting solid %i/%u...\n",i,header->n_solids-1);
        solids[i].loadSolid(file);

        if (i < header->n_solids - 1)
            solids[i+1].offset=solids[i].offset + solids[i].length;

        SAY("done.\n");
    }

    loadEntities(file);
    return 0;
}

int CScn::loadHeader(ifstream * file)
{
 	SAY("Getting header...");

 	//header=(scnHeader_t*) malloc(sizeof(struct scnHeader_t));
    header = new scnHeader_t;

	file->seekg(0);
    read_generic(header,file,sizeof(scnHeader_t));

	if (!str_nequals(header->magic,"NCSM",4))
		error(true,"CScn::loadHeader: Magic doesn't match, not a scn file!");

    if (header->version!=269)
		error(true,"CScn::loadHeader: Wrong scn file version!");

    SAY("done.\n");
	return 0;
}


int CScn::loadEntities(std::ifstream * file)
{

    u32 n_ents = header->n_ents;
    SAY("Getting %u Entities...",n_ents);

    ents = new (std::nothrow) CScnEnt[n_ents];

    if (ents==NULL)
        error(true,"Error allocating memory for CScnEnt");

    file->seekg(header->ents_offset2);

    u16 keylen;
    u16 vallen;
    CScnEnt * enti;
    char str1[128];
    char str2[128];

    for (u32 i=0;i<n_ents;i++)
    {
        enti=&ents[i];

        enti->n_fields=read_u32(file);
        enti->srefidx=read_u32(file);

        enti->fields = new (std::nothrow) CScnEnt::field[enti->n_fields];
        if (enti->fields == NULL)
            error(true,"Error allocating memory for %d fields of ent[%d]",enti->n_fields,i);

        for (int n=0;n<enti->n_fields;n++)
        {
            keylen=read_u16(file);
            vallen=read_u16(file);
            if (keylen >= 128 || vallen >= 128)
                error(true,"Ent[%i] has field %i with too large a string",i,n);

            read_generic(enti->fields[n].key,file,keylen);
            read_generic(enti->fields[n].value,file,vallen);

            //TODO: make sorted according to cell index
            if (str_equiv(str1,"Classname") && str_equiv(str2,"Cell"))
                cells.push_back(enti);
        }
    }
    SAY("%u done.\n",n_ents);
    return n_ents;
}

CScnEnt * CScn::getCell(u32 idx)
{
    CScnEnt * celli;
    string val;
    for (int i=0; i < cells.size(); i++)
    {
        celli = cells[i];
        val=celli->getField("cell_index");
        if (atoi(val.c_str()) == idx)
            return celli;
    }
    return NULL;
}









